package com.hdax.dm.order.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdax.dm.common.code.CodeEnum;
import com.hdax.dm.common.exception.DmException;
import com.hdax.dm.entity.item.Item;
import com.hdax.dm.entity.order.Order;
import com.hdax.dm.entity.order.OrderLinkUser;
import com.hdax.dm.entity.scheduler.SchedulerSeat;
import com.hdax.dm.entity.user.LinkUser;
import com.hdax.dm.order.dto.OrderDto;
import com.hdax.dm.order.feign.ItemFeign;
import com.hdax.dm.order.feign.LinkUserFeign;
import com.hdax.dm.order.feign.PriceFeign;
import com.hdax.dm.order.feign.SchedulerSeatFeign;
import com.hdax.dm.order.mappers.OrderMapper;
import com.hdax.dm.order.mq.RabbitConfig;
import com.hdax.dm.order.service.OrderLinkUserService;
import com.hdax.dm.order.service.OrderService;
import com.hdax.dm.order.vo.SubmitOrderVo;
import com.hdax.dm.token.TokenUtil;
import com.hdax.dm.utils.CommonResponse;
import com.hdax.dm.utils.ResponseUtil;
import org.apache.ibatis.annotations.Param;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private LinkUserFeign linkUserFeign;
    @Autowired
    private PriceFeign priceFeign;
    @Autowired
    private TokenUtil tokenUtil;
    @Autowired
    private OrderLinkUserService orderLinkUserService;
    @Autowired
    private SchedulerSeatFeign seatFeign;
    @Autowired
    private ItemFeign itemFeign;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitConfig rabbitConfig;
    @Autowired
    private OrderMapper orderMapper;




    @Override
    public CommonResponse submitOrder(Long UserId, SubmitOrderVo vo) throws DmException {

        //加锁
        boolean isLock=redisTemplate.opsForValue().setIfAbsent("lock","lock",500, TimeUnit.MILLISECONDS);


        if(!isLock){
            try {
                //线程0延迟执行
                Thread.sleep(5000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
            }
        }

        Long startTime = System.currentTimeMillis();//时间记录  开始时间

//        Long userId = tokenUtil.parseToken(token);
        if (UserId == 0L) {
            //登录超时,或者没有登录过/提交虚假订单
            try {
                throw new DmException(CodeEnum.USER_VCODE_NOT_TIMEOUT);
            } catch (DmException e) {
                e.printStackTrace();
            }
        }
        Order order = new Order();
        //生成唯一订单编号 雪花算法
        order.setOrderNo(IdUtil.getSnowflake().nextIdStr());
        order.setUserId(UserId);
        //获取购买商品的总价
        Long totalPrice = 0L;
        //先获取所有购买的座位
        //数组中存放的座位数据格式如下： x1_y1,x2_y2  1_1,1_2
        String[] seatPositions = vo.getSeatPositions().split(",");//拆分
        //获取订单联系人的相关信息
        // 数组数据格式如下： id1,id2,id3  1,120,121
        String[] linkIds = vo.getLinkIds().split(",");

        //保证人票一致
        if (seatPositions.length != linkIds.length) {
            try {
                throw new DmException(CodeEnum.USER_VCODE_NOT_UNANIMOUS);
            } catch (DmException e) {
                e.printStackTrace();
            }
        }

        //获取每个座位的横纵坐标
        for (int i = 0; i < seatPositions.length; i++) {


            String[] seatPosition = seatPositions[i].split("_");//二次拆分
            Long x = Long.parseLong(seatPosition[0]);
            Long y = Long.parseLong(seatPosition[1]);
            //根据scheduleId,x,y 查询座位的票价
            //当前商品的价格
            SchedulerSeat seata = priceFeign.price(vo.getSchedulerId(), x, y);
            //totalPrice总价
            totalPrice += seata.getPrice();


            //判断座位是否被别人提前购买了
            if (seata.getStatus()==2){
                throw new DmException(CodeEnum.Scheduler_VCODE_NOT_EXISTS);
            }


            //根据登录用户id和联系人id查询联系人相关信息
            LinkUser linkUser = linkUserFeign.linkUser(Long.parseLong(linkIds[i]), UserId);
            if (linkUser == null) {
                //联系人不存在
            }
            //循环新增订单联系人
            OrderLinkUser orderLinkUser = new OrderLinkUser();
            orderLinkUser.setOrderId(order.getOrderNo());
            orderLinkUser.setLinkUserId(linkUser.getId());
            orderLinkUser.setLinkUserName(linkUser.getName());
            orderLinkUser.setPrice(seata.getPrice().longValue());
            orderLinkUser.setX(x);
            orderLinkUser.setY(y);

            //调用数据库新增联系人

            try {
                orderLinkUserService.save(orderLinkUser);
            } catch (ArithmeticException e) {
                rabbitTemplate.convertAndSend("dm_ex_rollback", "linkuser", order.getOrderNo());
            }

            //修改座位的状态，需要锁定座位到某一订单
            SchedulerSeat seat = new SchedulerSeat();
            seat.setOrderNo(order.getOrderNo());
            seat.setScheduleId(vo.getSchedulerId());
            seat.setX(x);
            seat.setY(y);
//            seat.setAreaLevel(1L);
            seat.setUserId(UserId);
            //修改数据库(dm_schedule) 这个表dm_schedule_seat
            try {
                seatFeign.updateSeat(seat);//修改座位状态
            } catch (Exception e) {
                rabbitTemplate.convertAndSend("dm_ex_rollback", "seat", order.getOrderNo());
                //rabbitTemplate.convertAndSend(e);
            }
        }
        order.setSchedulerId(vo.getSchedulerId());//排期
        order.setItemId(vo.getItemId());
        //远程调用查询商品
        Item item = itemFeign.item(vo.getItemId());
        order.setItemName(item.getItemName());
        order.setTotalCount(Long.valueOf(seatPositions.length));
        //是否购买保险
        if (vo.getIsNeedInsurance() == 1) {
            order.setIsNeedInsurance(vo.getIsNeedInvoice());
            totalPrice += 20L;
        }
        //获取是否需要发票
        if (vo.getInvoiceType() == 1) {
            order.setInvoiceType(vo.getInvoiceType());
            if (vo.getInvoiceType() == 0) {
                //个人发票
                Short fap = 0;
                order.setInvoiceType(fap);
            } else if (vo.getInvoiceType() == 1) {
                //公司发票
                order.setInvoiceHead(vo.getInvoiceHead());
                order.setInvoiceNo(vo.getInvoiceNo());
            }
        }
        order.setOrderType(0L);
        order.setTotalAmount(totalPrice);
        try {
            //新增订单  并且数据库也要新增

            boolean a = this.save(order);
            if(a){
                rabbitTemplate.convertAndSend(rabbitConfig.getExchange(),rabbitConfig.getRoutingkey(),order.getOrderNo()
                        ,message -> {
                            //持久化数据
                            message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                            //120秒中自动进入死信队列里面
                            message.getMessageProperties().setExpiration("120000");
                            return message;
                        });
                return ResponseUtil.returnSuccess(order.getOrderNo());
            }

        } catch (Exception e) {
            rabbitTemplate.convertAndSend("dm_ex_rollback", "order", order.getOrderNo());
            rabbitTemplate.convertAndSend("dm_ex_rollback","seat",order.getOrderNo());
            rabbitTemplate.convertAndSend("dm_ex_rollback","order",order.getOrderNo());
        }
        Long endTime = System.currentTimeMillis();//时间记录  结束时间
        Long time = endTime - startTime;//当前方法执行的时间
        //解锁
        redisTemplate.delete("lock");
        return ResponseUtil.returnSuccess(order.getOrderNo());
    }

    @Override
    public Boolean deleteOrder(String orderNo) {
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("orderNo",orderNo);
        return remove(updateWrapper);
    }

    @Override
    public Order getOrder(String orderNo) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("orderNo",orderNo);
        return getOne(queryWrapper);
    }

    /**
     * 订单添加支付宝订单号
     * @param orderNo
     * @param tradeNo
     * @return
     */
    @Override
    public Boolean updateOrder(String orderNo, String tradeNo) {
        return baseMapper.updateOrder(orderNo, tradeNo);
    }

    @Override
    public Order order(String orderNo) {
        return baseMapper.order(orderNo);
    }

    @Override
    public Boolean updateOrderChao(String orderNo) {
        return baseMapper.updateOrderChao(orderNo);
    }

    @Override
    public CommonResponse cancelOrder(String orderNo) {
        //TODO:分布式事务
        //将订单状态改为已取消
        orderMapper.updateOrderOne(orderNo);
        //释放座位
        seatFeign.updateSeatOne(orderNo);
        return ResponseUtil.returnSuccess("");
    }

    @Override
    public Order selectOne(String orderNo) {
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("orderNo",orderNo);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public boolean updateOrderTwo(String orderNo) {
        //查出金额
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("orderNo",orderNo);
        Order order = baseMapper.selectOne(queryWrapper);
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("orderNo",orderNo);
        updateWrapper.set("orderType",5);
        //将值变为负值
        updateWrapper.set("totalAmount",("-"+order.getTotalAmount()));
        return this.update(updateWrapper);
    }

}
